#!D:\Program_Files\Python27\python.exe

import wx
import wx.xrc as xrc
import wx.grid as gridlib
import datetime, os, sys, gc

try:
    dirName = os.path.dirname(os.path.abspath(__file__))
except:
    dirName = os.path.dirname(os.path.abspath(sys.argv[0]))

sys.path.append(os.path.split(dirName)[0])

try:
    import agw.flatnotebook as FNB
except ImportError: # if it's not there locally, try the wxPython lib.
    import wx.lib.agw.flatnotebook as FNB


#=|start of class SqlScriptPanel|=====================================
class SqlScriptPanel(wx.Panel):
    def __init__(self, parent, appContext, scriptStr=None):
        self.__appContext = appContext
        pre = wx.PrePanel()
        res = xrc.EmptyXmlResource()
        res.Load("xrc_file/scriptPage.xrc")
        res.LoadOnPanel(pre, parent, "scriptPage")
        self.PostCreate(pre)

        self.text_codeinput = xrc.XRCCTRL(self, 'text_codeinput', wx.TextCtrl)
        if scriptStr != None:
            self.text_codeinput.SetValue(scriptStr)
        self.ctrl_seperator = xrc.XRCCTRL(self, 'txtCtrl_seperator', wx.TextCtrl)
        self.ctrl_autocommit = xrc.XRCCTRL(self, 'cb_autocommit', wx.CheckBox)
        self.panel_result = xrc.XRCCTRL(self, 'panel_result', wx.Panel)
        try:
            result_grid_count = self.appContext['cfg']['result_grid_count']
        except KeyError:
            result_grid_count = 5
        self.resultGridSet = QueryResultGroup(self.appContext, result_grid_count, self.panel_result)
        vbox = wx.BoxSizer(wx.VERTICAL)
        vbox.Add(self.resultGridSet, 1, wx.EXPAND | wx.ALL, 3)
        self.panel_result.SetSizer(vbox)

        pass
    
    @property
    def appContext(self):return self.__appContext

    def EvtChoice(self, event):
        choice = event.GetString()
        if choice == "--new--":
            pass
        else :
            pass
        pass
    
    def getAutoCommitStatus(self):
        return self.ctrl_autocommit.IsChecked()
    def getSeperator(self):
        return self.ctrl_seperator.GetValue()
    def getScript(self):
        return self.text_codeinput.GetValue()
    
    def packResultSet(self, queryResultSet):
        assert "dct_scp.py SqlScriptPanel.packResultSet"
        self.resultGridSet.packResultSet(queryResultSet)
        pass
    
    def refreshTable(self, queryResult):
        table = QueryResultTable(queryResult)
        self.grid_result.SetTable(table, True)
        self.grid_result.SetRowLabelSize(0)
        self.grid_result.SetMargins(0,0)
        self.grid_result.AutoSizeColumns(False)
        pass
    
    pass
#=|end of class SqlScriptPanel|=====================================


#=|start of class QueryResultGroup|=================================
class QueryResultGroup(FNB.FlatNotebook):
    def __init__(self, appContext, maxSheetCount = 3, parent=None):
        FNB.FlatNotebook.__init__(self, parent = parent)
#         super(FNB.FlatNotebook, self)
        self.__maxShtCnt = maxSheetCount
        self.__gridSet = dict()
        self.__appContext = appContext
        pass
    
    @property
    def maxSheetCount(self):return self.__maxShtCnt
    @maxSheetCount.setter
    def maxSheetCount(self, val):self.__maxShtCnt = val
    
    @property
    def gridSet(self): return self.__gridSet
    @property
    def appContext(self): return self.__appContext
    
    def packResultSet(self, queryResultSet):
        for i in range(len(queryResultSet)):
            if len(self.__gridSet) < self.maxSheetCount :
                self.addNewPageForResult(queryResultSet[i])
                pass
            else:
                self.updatePageForResult(queryResultSet[i], \
                                         i % self.maxSheetCount \
                                        )
                pass
            pass
        pass
    
    def addNewPageForResult(self, queryResult):
        cnt = len(self.gridSet)
        g1 = QueryResultGrid(self.appContext, parent=self)
        self.gridSet[cnt] = g1
        
        self.AddPage(g1, str(cnt+1))
        
        self.updatePageForResult(queryResult, cnt)
        pass
    
    def updatePageForResult(self, queryResult, idx):
        g1 = self.gridSet[idx]
        g1.setGridData(queryResult)
        self.SetSelection(idx)
        pass
    
    pass
#=|end of class QueryResultGroup|=================================


#=|start of class QueryResultTable|=================================
class QueryResultTable(gridlib.PyGridTableBase):
    def __init__(self, queryResult):
        gridlib.PyGridTableBase.__init__(self)
        self.tbData = queryResult
        self.colLabels = self.tbData[1]
        self.dataTypes = self.tbData[2]
        self.data = self.tbData[0]
    
    # required methods for the wxPyGridTableBase interface
    def GetNumberRows(self):
        return len(self.data) + 1
    def GetNumberCols(self):
        return len(self.colLabels)
    def IsEmptyCell(self, row, col):
        try:
            return not self.data[row][col]
        except IndexError:
            return True
    # Get/Set values in the table.  The Python version of these
    # methods can handle any data-type, (as long as the Editor and
    # Renderer understands the type too,) not just strings as in the
    # C++ version.
    def GetValue(self, row, col):
        try:
            return self.data[row][col]
        except IndexError:
            return ''

    def GetValueAsCustom (self, row, col, typeName):
        res = None
        if typeName in ['bigint', 'int']:
            res = self.GetValueAsLong(row, col)
        elif typeName == 'string':
            res = self.GetValue(row, col)
        elif typeName == 'timestamp':
            value = self.GetValue(row, col)
            ts = datetime.datetime.strptime(value, "%Y-%m-%d %H:%M:%S.%f") 
            var_str = ts.year + '-' + ts.month + '-' + ts.day + ' ' \
                      + ts.hour + ':' + ts.minute  + ':' + ts.second \
                      + '.' + ts.microsecond
            res = var_str
        elif typeName in ['blob','clob']:
            res = '...'
        elif typeName == 'date':
            pass
        elif typeName in ['real', 'decimal']:
            res = self.GetValueAsDouble(row, col)
        elif typeName == 'time':
            pass
        else :
            res = ''
        return res
        pass
    
    def SetValue(self, row, col, value):
        def innerSetValue(row, col, value):
            try:
                self.data[row][col] = value
            except IndexError:
                # add a new row
                self.data.append([''] * self.GetNumberCols())
                innerSetValue(row, col, value)
                # tell the grid we've added a row
                msg = gridlib.GridTableMessage(self,            # The table
                        gridlib.GRIDTABLE_NOTIFY_ROWS_APPENDED, # what we did to it
                        1                                       # how many
                        )
                self.GetView().ProcessTableMessage(msg)
        innerSetValue(row, col, value)

    def SetValueAsCustom(self, row, col, typeName, value):
        if typeName in ['bigint', 'int']:
            self.SetValueAsLong(row, col, value)
        elif typeName == 'string':
            self.SetValue(row, col, value)
        elif typeName == 'timestamp':
            ts = datetime.datetime.strptime(value, "%Y-%m-%d %H:%M:%S.%f") 
            var_str = ts.year + '-' + ts.month + '-' + ts.day + ' ' \
                      + ts.hour + ':' + ts.minute  + ':' + ts.second \
                      + '.' + ts.microsecond
            #'2014-11-16 20:37:42.001000'
            self.SetValue(row, col, var_str)
        elif typeName in ['blob','clob']:
            self.SetValue(row, col, '...')
        elif typeName == 'date':
            pass
        elif typeName in ['real', 'decimal']:
            self.SetValueAsDouble(row, col, value)
        elif typeName == 'time':
            pass
        else :
            pass
        
        pass
    
    # Some optional methods
    # Called when the grid needs to display labels
    def GetColLabelValue(self, col):
        return self.colLabels[col]
    # Called to determine the kind of editor/renderer to use by
    # default, doesn't necessarily have to be the same type used
    # natively by the editor/renderer if they know how to convert.
    def GetTypeName(self, row, col):
        return self.dataTypes[col]
    # Called to determine how the data can be fetched and stored by the
    # editor and renderer.  This allows you to enforce some type-safety
    # in the grid.
    def CanGetValueAs(self, row, col, typeName):
        colType = self.dataTypes[col].split(':')[0]
        if typeName == colType:
            return True
        else:
            return False
    def CanSetValueAs(self, row, col, typeName):
        return self.CanGetValueAs(row, col, typeName)
    
    pass
#=|end of class QueryResultTable|=================================


#=|start of class QueryResultGrid|=================================
##class QueryResultGrid(gridlib.Grid):
class QueryResultGrid(gridlib.Grid):
    def __init__(self, appContext, parent=None):
        gridlib.Grid.__init__(self, parent = parent)
        self.__appCtxt = appContext
        self.__table = None
        pass
    
    @property
    def dataTable(self):return self.__table
    @dataTable.setter
    def dataTable(self, val):
        del self.__table
        gc.collect()
        self.__table = val
        pass
    
    def setGridData(self, queryResult):
        self.dataTable = QueryResultTable(queryResult)
        self.SetTable(self.dataTable)
        pass
    
    pass
#=|end of class QueryResultGrid|=================================